package org.jeecg.modules.xxgx.common.util;


import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.jeecg.modules.xxgx.djgl.constant.NumberConstant;

import java.math.BigDecimal;

/**
 * 发票金额计算工具类（保留小数位）
 * @author
 */
public class InvoiceCalcUtil {

    public static BigDecimal toBigDecimal(String str){
        return toBigDecimal(str,null);
    }
    public static BigDecimal toBigDecimal(String str,BigDecimal defaultValue){
        if (str == null) {
            return defaultValue;
        } else {
            try {
                return new BigDecimal(str);
            } catch (NumberFormatException var4) {
                return defaultValue;
            }
        }
    }

    /**
     * 返回小数保存位置（原格式输出）
     * @param value
     * @param precLength
     * @return
     */
    public static BigDecimal getValue(BigDecimal value,int precLength){
        return value.setScale(precLength,BigDecimal.ROUND_HALF_UP);
    }
    /**
     * 返回小数保存位置,并去掉小数点后边多余的0
     * @param value
     * @param precLength
     * @return
     */
    public static BigDecimal getValueTrimZero(BigDecimal value,int precLength){
        return new BigDecimal(value.setScale(precLength,BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
    }
    public static BigDecimal getValueTrimZero(BigDecimal value){
        return new BigDecimal(value.stripTrailingZeros().toPlainString());
    }
    public static BigDecimal getValueTrimZero(String value){
        BigDecimal tmpValue=new BigDecimal(value);
        return getValueTrimZero(tmpValue);
    }
    /**
     * 计算不含税金额
     * @param je 含税金额
     * @param tax 税率
     * @return
     */
    public static BigDecimal calcNoTaxAmount(BigDecimal je,BigDecimal tax){
        if(tax==null||tax.compareTo(BigDecimal.ZERO)==0){
            return je;
        }
        //不含税金额=含税金额/(1+税率)
        //含税金额=不含税金额+税额=不含税金额+不含税金额X税率=不含税金额*(1+税率)
        //税额=不含税金额X税率
        return je.divide(BigDecimal.ONE.add(tax), NumberConstant.NUM_2,BigDecimal.ROUND_HALF_UP);
    }
    /**
     * 根据金额计算数量
     * @param je
     * @param price
     * @return
     */
    public static BigDecimal calcQuantity(BigDecimal je,BigDecimal price){
        return calcQuantity(je,price,null);
    }

    /**
     * 根据金额、价格计算数量
     * @param je
     * @param price
     * @param fplxdm
     * @return
     */
    public static BigDecimal calcQuantity(BigDecimal je,BigDecimal price,String fplxdm){
        if(price==null ||price.equals(BigDecimal.ZERO)) {
            return null;
        }
        //数电：最大长度16，小数点最大长度13位，不含小数点
        //税控票-核心板：整数位不能超过14位，小数位不超过18位；商品数量*单价=金额 误差正负0.01,处理时人为界定折中法
        BigDecimal quantity=je.divide(price, NumberConstant.NUM_13,BigDecimal.ROUND_HALF_UP);
        //根据数量的总长度，重新计算小数位
        return getQuantityOrPriceValue(quantity,NumberConstant.NUM_18);
    }


    /**
     * 根据金额、数量计算价格
     * @param je
     * @param quantity
     * @return
     */
    public static BigDecimal calcPrice(BigDecimal je,BigDecimal quantity){
        return calcPrice(je,quantity,null);
    }

    /**
     * 根据金额、数量计算价格
     * @param je
     * @param quantity
     * @param fplxdm
     * @return
     */
    public static BigDecimal calcPrice(BigDecimal je,BigDecimal quantity,String fplxdm){
        if(quantity==null ||quantity.equals(BigDecimal.ZERO)) {
            return null;
        }
        //数电：最大长度16，小数点最大长度13位，不含小数点
        //税控票-核心板：整数位不能超过14位，小数位不超过18位；商品数量*单价=金额 误差正负0.01,处理时人为界定折中法
        BigDecimal price=je.divide(quantity,NumberConstant.NUM_13,BigDecimal.ROUND_HALF_UP);
        //根据数量的总长度，重新计算小数位
        return getQuantityOrPriceValue(price,NumberConstant.NUM_18);
    }

    /**
     * 根据值总长度，重新计算保留的小数位
     * @param value
     * @param totalLength
     * @return
     */
    private static BigDecimal getQuantityOrPriceValue(BigDecimal value,int totalLength){
        if(value==null){
            return value;
        }

        //0直接返回,不然向后计算就变成科学计数了
        if(NumberUtils.toDouble(value)==0){
            //(先转字符串，再转对应类型,不然会有科学数)
            return new BigDecimal(value.stripTrailingZeros().toPlainString());
        }
        //去掉负号
        String valueStr=String.valueOf(value).replace("-","");

        //如果小于总长度直接返回，并去掉小数点后边多余的0
        if(valueStr.length()<=totalLength){
            //去掉小数点后边多余的0(先转字符串，再转对应类型,不然会有科学数)
            return  new BigDecimal(value.stripTrailingZeros().toPlainString());
        }
        //小数点所在位置
        int posIndex=valueStr.indexOf(".");
        //整数值直接返
        if(posIndex==NumberConstant.NUM_NEGATIVE_1){
            return value;
        }

        //获取整数部分的值
        String s1=valueStr;
        //默认“."小数点的长度是一位，如果没有小数了则为0
        int digitLength=NumberConstant.NUM_1;
        if(posIndex!=NumberConstant.NUM_NEGATIVE_1){
            //包含小数点时的处理
            s1=valueStr.substring(NumberConstant.NUM_0,posIndex);
        }
        if(s1.length()>totalLength){
            throw new RuntimeException(valueStr+"整数部分超过最大长度"+String.valueOf(totalLength));
        }

        //计算小数部分长度
        int precLength=totalLength-s1.length()-digitLength;
        //重新处理一下小数位(先转字符串，再转对应类型,不然会有科学数)
        BigDecimal newValue=value.setScale(precLength,BigDecimal.ROUND_HALF_UP);
        return new BigDecimal(newValue.stripTrailingZeros().toPlainString());
    }

    /**
     * 清空商品大类的名称
     *
     * @param goodsName
     * @return
     */
    public static String clearGoodsCategory(String goodsName) {
        if (StringUtils.isEmpty(goodsName)) {
            return goodsName;
        }

        int secPosition = goodsName.indexOf("*", 2);
        if (secPosition <= 0) {
            return goodsName;
        }

        String sTmp = goodsName.substring(secPosition + 1);
        return sTmp;
    }

    /**
     * 根据商品名称获取商品大类的名称
     *
     * @param goodsName
     * @return
     */
    public static String getGoodsCategory(String goodsName) {
        String sTmp=null;
        if (StringUtils.isNotEmpty(goodsName)&&goodsName.startsWith("*")) {
            int secPosition = goodsName.indexOf("*", 2);
            if (secPosition <= 0) {
                return null;
            }
            sTmp = goodsName.substring(1,secPosition);
        }
        return sTmp;
    }
}
